import System.Directory (doesDirectoryExist, doesFileExist,
                         getCurrentDirectory, getDirectoryContents)
import System.Environment(getArgs)
import System.FilePath --((</>))
import System.IO
import System.Process
import Control.Monad (forM)
import Text.Printf
import Text.Regex.Posix
import Data.List

data RRDInfo = RRDInfo {
      rrdFullPath :: String,
      rrdFName :: String,
      rrdDS :: String,
      rrdCF :: String
    } deriving Show

data RRDRunner = RRDRunner {
      rrdCmd :: String,
      rrdImgName :: String
    } deriving Show

main = do
  argv <- getArgs
  let dirname = if null argv 
                then error "Please provide a directory name!" 
                else head argv
  putStrLn "<html><body> <!--"
  putStrLn $ "Directory: " ++ dirname
  files <- getRecursiveContents dirname
  rrds_complete <- mapM (\fn -> readProcess "rrdtool" ["info",fn] []) $ filter ((".rrd" ==) . (reverse . take 4 . reverse)) files
  let rrdinfos = parseAllRRDToolInfo files rrds_complete
  let rrdcmds = map rrdgraphGen rrdinfos
  ret <- mapM (system . rrdCmd) rrdcmds
  print ret
  putStrLn "--!>"
  putStrLn $ intercalate "\n" $ map buildHTML rrdcmds
  putStrLn "</body></html>"

buildHTML :: RRDRunner -> String
buildHTML x = intercalate "\n" [printf "<h1>%s</h1>" imgname, printf "\t<img align=\"center\" src=\"%s\" alt=\"%s\">" imgname imgname, printf "<!-- %s --!>" $ rrdCmd x]
    where imgname = rrdImgName x


rrdgraphGen :: RRDInfo -> RRDRunner
rrdgraphGen ri = RRDRunner ("rrdtool graph " ++ intercalate "  " [targetname,"-f \"\"","--lazy","-w 800","-h 300",printf "DEF:%s_%s=%s:%s:%s" ds cf fpath ds cf,printf "LINE1:%s_%s%s:\"%s %s\"" ds cf "#ff0000" ds cf]) targetname
    where ds = rrdDS ri
          cf = rrdCF ri
          fpath = rrdFullPath ri
          targetname = rrdFName ri ++ ds ++ cf ++ ".png"

parseAllRRDToolInfo :: [String] -> [String] -> [RRDInfo]
parseAllRRDToolInfo files xs = let rrds = map lines xs
                                   rrd_datasources = map (getOnlyMatches . findDSRegex ) rrds
                                   rrd_consolidation_functions =  map (getOnlyMatches . findCFRegex ) rrds
                               in getRRDInfos $ zip files $ zip rrd_datasources rrd_consolidation_functions

getRRDInfos :: [(String,([String],[String]))] -> [RRDInfo]
getRRDInfos xs = concatMap getinfo xs
    where getinfo x = [RRDInfo fpath (snd $ splitFileName fpath) y z | y <- ds, z <- cf]
              where fpath = fst x
                    dsncf = snd x
                    ds = fst dsncf
                    cf = snd dsncf

getOnlyMatches :: [(String,String,String,[String])] -> [String]
getOnlyMatches xs = nub $ concatMap onlyList xs
    where onlyList (_,_,_,l) = l


findDSRegex :: [String] -> [(String,String,String,[String])]
findDSRegex xs = map searchRX xs
    where searchRX = (=~ "ds\\[([a-zA-z]+)\\].type =")


findCFRegex :: [String] -> [(String,String,String,[String])]
findCFRegex xs = map searchRX xs
    where searchRX = (=~ "rra.[0-9]+.\\.cf = \"([A-Za-z]+)\"")


getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents topdir = do
  names <- getDirectoryContents topdir
  let properNames = filter (`notElem` [".", ".."]) names
  paths <- forM properNames $ \name -> do
    let path = topdir </> name
    isDirectory <- doesDirectoryExist path
    if isDirectory
      then getRecursiveContents path
      else return [path]
  return (concat paths)

